﻿using System;
using System.Drawing;
using System.Windows.Forms;
using Accord.Imaging;
using Accord.Imaging.Filters;
using Accord.Math;
using AForge;
using AForge.Imaging.Filters;
using System.Threading;
using System.Collections.Generic;

namespace VideoFlowStatistics.Class
{
    class Panorama
    {
        public Bitmap ImageOne { get; set; }
        public Bitmap ImageTwo { get; set; }
        public Bitmap ImageThree { get; set; }

        private Bitmap ImageTmp { get; set; }

        private IntPoint[] harrisPoints1;
        private IntPoint[] harrisPoints2;

        private IntPoint[] correlationPoints1;
        private IntPoint[] correlationPoints2;

        private MatrixH homography;

        private HarrisCornersDetector harris;

        List<float[]> listFloat = new List<float[]>();

        public Panorama()
        {
            if (harris == null)
                harris = new HarrisCornersDetector(
                 HarrisCornerMeasure.Harris, 20000f, 1.4f, 5);
        }
        /// <summary>
        ///图片合成处理
        /// </summary>
        /// <returns></returns>
        public Bitmap ImagePanorama()
        {
            if (ImageOne != null && ImageTwo != null&&ImageThree==null)
            {
                return Sypicture(ImageOne, ImageTwo);
            }
            else if (ImageOne != null && ImageTwo != null && ImageThree != null)
            {
                Bitmap img = Sypicture(ImageOne, ImageTwo);

                return Sypicture(img, ImageThree);
            }
            return null;
        }

        /// <summary>
        /// 图片拼接合成
        /// </summary>
        /// <returns></returns>
        public Bitmap ImageMerger()
        {
            if (ImageOne != null && ImageTwo != null && ImageThree == null)
            {
                return Merger(ImageOne, ImageTwo);
            }
            else if (ImageOne != null && ImageTwo != null && ImageThree != null)
            {
                Bitmap img = Merger(ImageOne, ImageTwo);

                return Merger(img, ImageThree);
            }
            return null;
        }

        private Bitmap Sypicture(Bitmap tmpImageOne, Bitmap tmpImageTwo)
        {
            if (tmpImageOne == null || tmpImageTwo == null)
            {
                return null;
            }
            try
            {
                if (Properties.Settings.Default.IsCollect == "1")//1记录位置
                {
                    // Step 1: Detect feature points using Harris Corners Detector
                    harrisPoints1 = harris.ProcessImage(tmpImageOne).ToArray();
                    harrisPoints2 = harris.ProcessImage(tmpImageTwo).ToArray();

                    // Show the marked points in the original images
                    Bitmap img1mark = new PointsMarker(harrisPoints1).Apply(tmpImageOne);
                    Bitmap img2mark = new PointsMarker(harrisPoints2).Apply(tmpImageTwo);

                    // Step 2: Match feature points using a correlation measure
                    CorrelationMatching matcher = new CorrelationMatching(9);
                    IntPoint[][] matches = matcher.Match(tmpImageOne, tmpImageTwo, harrisPoints1, harrisPoints2);

                    // Get the two sets of points
                    correlationPoints1 = matches[0];
                    correlationPoints2 = matches[1];

                    // Step 3: Create the homography matrix using a robust estimator
                    if (correlationPoints1.Length < 4 || correlationPoints2.Length < 4)
                    {
                        return null;
                    }

                    RansacHomographyEstimator ransac = new RansacHomographyEstimator(0.001, 0.99);
                    homography = ransac.Estimate(correlationPoints1, correlationPoints2);

                    //记录位置
                    listFloat.Add(homography.Elements);

                    // Step 4: Project and blend the second image using the homography
                    Blend blend = new Blend(homography, tmpImageOne);
                    return blend.Apply(tmpImageTwo);
                }
                else if (Properties.Settings.Default.IsCollect == "2")//2写入记录
                {
                    if (listFloat.Count > 0)
                    {
                        txtControl.Insert(listFloat);
                        listFloat.Clear();
                    }
                    return tmpImageOne;
                }
                else
                {
                    string[] matrixH = Properties.Settings.Default.MatrixH.Split(',');
                    if (string.IsNullOrEmpty(Properties.Settings.Default.MatrixH)) return tmpImageOne;
                    homography = new MatrixH(float.Parse(matrixH[0]), float.Parse(matrixH[1]), float.Parse(matrixH[2]), float.Parse(matrixH[3]), float.Parse(matrixH[4]), float.Parse(matrixH[5]), float.Parse(matrixH[6]), float.Parse(matrixH[7]));
                    Blend blend = new Blend(homography, tmpImageOne);
                    return blend.Apply(tmpImageTwo);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return null;
            }
        }

        private Bitmap Merger(Bitmap tmpImageOne, Bitmap tmpImageTwo)
        {
            if (tmpImageOne == null || tmpImageTwo == null)
            {
                return null;
            }
            // Step 1: Detect feature points using Harris Corners Detector
            HarrisCornersDetector harris = new HarrisCornersDetector(
                HarrisCornerMeasure.Harris, 20000f, 1.4f, 5);
            harrisPoints1 = harris.ProcessImage(tmpImageOne).ToArray();
            harrisPoints2 = harris.ProcessImage(tmpImageTwo).ToArray();

            // Show the marked points in the original images
            Bitmap img1mark = new PointsMarker(harrisPoints1).Apply(tmpImageOne);
            Bitmap img2mark = new PointsMarker(harrisPoints2).Apply(tmpImageTwo);

            // Concatenate the two images together in a single image (just to show on screen)
            Concatenate concatenate = new Concatenate(img1mark);
           return concatenate.Apply(img2mark);
        }
        // Lock it
        public void Lock()
        {
            Monitor.Enter(this);
        }

        // Unlock it
        public void Unlock()
        {
            Monitor.Exit(this);
        }
    }
}
